package net.phoenix.repository;

import java.util.ArrayList;
import java.util.Calendar;

import javax.jcr.Node;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
import net.phoenix.repository.utils.AntPathMatcher;

/**
 * 
 * Jigsaw server
 * 
 * @author <a href="shamphone@gmail.com">Li XiongFeng</a>
 * @date 2012-1-2
 * @version 1.0.0
 */
public class JCRUtils {

	public static PropertyDefinition getPropertyDefinition(NodeDefinition nodeDefinition, String propertyName) {
		return getPropertyDefinition(nodeDefinition.getDefaultPrimaryType(), propertyName);
	}


	public static PropertyDefinition getPropertyDefinition(NodeType nodeType, String propertyName) {
		for (PropertyDefinition property : nodeType.getPropertyDefinitions()) {
			if (property.getName().equals(propertyName))
				return property;
		}
		AntPathMatcher matcher = new AntPathMatcher();
		for (PropertyDefinition property : nodeType.getPropertyDefinitions()) {
			if (matcher.match(property.getName(), propertyName))
				return property;
		}
		return null;
	}

	public static PropertyDefinition getPropertyDefinition(Node node, String propertyName) throws RepositoryException {
		NodeType nodeType = node.getPrimaryNodeType();
		PropertyDefinition definition = getPropertyDefinition(nodeType, propertyName);
		if (definition != null)
			return definition;
		for (NodeType type : node.getMixinNodeTypes()) {
			definition = getPropertyDefinition(type, propertyName);
			if (definition != null)
				return definition;
		}

		return null;
	}

	public static NodeDefinition getChildNodeDefinition(NodeDefinition parent, String name) {
		for (NodeDefinition definition : parent.getDefaultPrimaryType().getChildNodeDefinitions()) {
			if (definition.getName().equals(name)) {
				return definition;
			}
		}
		AntPathMatcher matcher = new AntPathMatcher();
		for (NodeDefinition definition : parent.getDefaultPrimaryType().getChildNodeDefinitions()) {
			if (matcher.match(definition.getName(), name)) {
				return definition;
			}
		}
		return null;
	}

	public static NodeDefinition getChildNodeDefinition(NodeType parent, String name) {
		for (NodeDefinition definition : parent.getChildNodeDefinitions()) {
			if (definition.getName().equals(name)) {
				return definition;
			}
		}
		AntPathMatcher matcher = new AntPathMatcher();
		for (NodeDefinition definition : parent.getChildNodeDefinitions()) {
			if (matcher.match(definition.getName(), name)) {
				return definition;
			}
		}
		return null;
	}

	public static NodeType getChildNodeType(NodeType parent, String name) {
		for (NodeDefinition definition : parent.getChildNodeDefinitions()) {
			if (definition.getName().equals(name)) {
				return definition.getDefaultPrimaryType();
			}
		}
		AntPathMatcher matcher = new AntPathMatcher();
		for (NodeDefinition definition : parent.getChildNodeDefinitions()) {
			if (matcher.match(definition.getName(), name)) {
				return definition.getDefaultPrimaryType();
			}
		}
		return null;
	}

	/**
	 * 验证数据类型是否合适
	 * 
	 * @param value
	 *            Value
	 * @param type
	 *            int
	 * @return boolean
	 * @throws RepositoryException
	 * @throws IllegalStateException
	 */
	public static boolean checkType(Value value, int type) throws RepositoryException {
		try {
			switch (type) {
			case PropertyType.STRING:
				value.getString();
				break;

			case PropertyType.BINARY:
				value.getStream();
				break;
			case PropertyType.BOOLEAN:
				value.getBoolean();
				break;
			case PropertyType.DATE:
				value.getDate();
				break;
			case PropertyType.DOUBLE:
				value.getDouble();
				break;
			case PropertyType.LONG:
				value.getLong();
				break;
			case PropertyType.NAME:
				value.getString();
				break;
			case PropertyType.PATH:
				value.getString();
				break;
			case PropertyType.REFERENCE:
				value.getString();
				break;
			// case PropertyType.TEXT:
			// value.getString();
			// break;
			default:
				return false;
			}
			return true;
		} catch (ValueFormatException vfe) {
			return false;
		}
	}

	public static String[] toStringArray(Value[] values) throws RepositoryException {
		ArrayList<String> result = new ArrayList<String>();
		for (int i = 0; i < values.length; i++) {
			String value = values[i].getString();
			if (value != null)
				result.add(value);
		}
		return (String[]) result.toArray(new String[result.size()]);
	}

	public static boolean[] toBooleanArray(Value[] values) throws RepositoryException {
		boolean[] result = new boolean[values.length];
		for (int i = 0; i < values.length; i++)
			result[i] = values[i].getBoolean();
		return result;
	}

	public static Calendar[] toCalendarArray(Value[] values) throws RepositoryException {
		Calendar[] result = new Calendar[values.length];
		for (int i = 0; i < values.length; i++)
			result[i] = values[i].getDate();
		return result;
	}

	public static long[] toLongArray(Value[] values) throws RepositoryException {
		long[] result = new long[values.length];
		for (int i = 0; i < values.length; i++)
			result[i] = values[i].getLong();
		return result;
	}

	public static double[] toDoubleArray(Value[] values) throws RepositoryException {
		double[] result = new double[values.length];
		for (int i = 0; i < values.length; i++)
			result[i] = values[i].getDouble();
		return result;
	}

	/**
	 * @param values
	 * @return
	 * @throws RepositoryException
	 */
	// public static Node[] toNodeArray(Value[] values) throws
	// RepositoryException {
	// List<Node> list = new ArrayList<Node>();
	// for (int i = 0; i < values.length; i++) {
	// Node node = ((InternalValue) values[i]).getReference();
	// if (node != null) {
	// list.add(node);
	// }
	// }
	// Node[] nodes = (Node[]) list.toArray(new Node[list.size()]);
	// return nodes;
	// }

}
